package com.zsk.tool.file;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

/**
 * File opration
 * 
 * @author zincredible
 * @date 2019/04/02 13:51:39
 */

public class FileUtil {

    private final static DecimalFormat TWOPOINT_FORMAT = new DecimalFormat("#.00");

    /**
     * make dir
     * 
     * @param dirPath
     */
    public static void makeDir(String dirPath) {
        File file = new File(dirPath);
        if (!file.isDirectory()) {
            file.mkdirs();
        }
    }

    /**
     * Unzip file
     * 
     * @param zipFile
     *            zip fike
     * @param desFile
     *            target dir
     * @throws IOException
     */
    public static void unZip(File zipFile, File desFile) {

        try (ZipFile zf = new ZipFile(zipFile)) {
            System.out.println("input zip file " + zipFile.getCanonicalPath());
            System.out.println("unzip dir " + desFile.getCanonicalPath());
            String dirPath = desFile.getCanonicalPath();
            Enumeration<?> e = zf.entries();
            while (e.hasMoreElements()) {
                ZipEntry ze2 = (ZipEntry)e.nextElement();
                String entryName = ze2.getName();
                String path = dirPath + "/" + entryName;
                if (ze2.isDirectory()) {
                    File decompressDirFile = new File(path);
                    if (!decompressDirFile.exists()) {
                        decompressDirFile.mkdirs();
                    }
                } else {
                    String fileDir = path.substring(0, path.lastIndexOf("/"));
                    File fileDirFile = new File(fileDir);
                    if (!fileDirFile.exists()) {
                        fileDirFile.mkdirs();
                    }

                    try (
                        BufferedOutputStream bos =
                            new BufferedOutputStream(new FileOutputStream(dirPath + "/" + entryName));
                        BufferedInputStream bi = new BufferedInputStream(zf.getInputStream(ze2));) {

                        byte[] readContent = new byte[1024];
                        int readCount = bi.read(readContent);
                        while (readCount != -1) {
                            bos.write(readContent, 0, readCount);
                            readCount = bi.read(readContent);
                        }
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            }
            System.out.println("unzip file " + zipFile.getCanonicalPath() + " success");
        } catch (ZipException e1) {
            e1.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }

    public static void close(OutputStream os) {
        if (os != null) {
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void close(InputStream os) {
        if (os != null) {
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void deleteDir(String dir) {
        File dirFile = new File(dir);
        deleteFileOrFolder(dirFile);
    }

    /**
     * Delete file directory
     * 
     * @param dir
     */
    public static void deleteFileOrFolder(File file) {
        if (file == null || !file.exists() || !file.isDirectory()) {
            return;
        }
        for (File f : file.listFiles()) {
            if (f.isFile()) {
                f.delete();
            } else if (file.isDirectory()) {
                deleteFileOrFolder(f);
            }
        }
        file.delete();
    }

    /**
     * Clear the folder and create one if it does not exist
     * 
     * @param dir
     */
    public static void emptyDir(String dir) {
        try {
            File dirFile = new File(dir);
            deleteFileOrFolder(dirFile);
            dirFile.mkdirs();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Clear the folder and create one if it does not exist
     * 
     * @param dir
     */
    public static void emptyDir(File dir) {
        deleteFileOrFolder(dir);
        dir.mkdirs();
    }

    /**
     * 精确到两位小数
     * 
     * @param num
     * @return
     */
    public static double getTwoPointNum(double num) {
        String str = TWOPOINT_FORMAT.format(num);
        double temp = Double.valueOf(str);
        return temp;
    }

    /**
     * byte 换算成KB或MB
     * 
     * @param size
     * @return
     */
    public static String getFileSize(long size) {
        String fileSize = "";
        if (size > 1024 * 1024) {
            double lenght = size / 1024.0 / 1024.0;
            fileSize = getTwoPointNum(lenght) + "MB";
            return fileSize;
        }
        double lenght = size / 1024.0;
        fileSize = getTwoPointNum(lenght) + "KB";
        return fileSize;
    }

    /**
     * 获取文件夹大小
     * 
     * @param file
     * @return
     */
    private static long getTotalSizeOfFilesInDir(final File file) {
        if (file.isFile()) {
            return file.length();
        }
        final File[] children = file.listFiles();
        long total = 0;
        if (children != null) {
            for (final File child : children) {
                total += getTotalSizeOfFilesInDir(child);
            }
        }
        return total;
    }

    /**
     * 获取文件夹下文件大小
     * 
     * @return
     */
    public static String getDirSize(String dir) {
        String size = "";
        try {
            File file = new File(dir);
            size = getFileSize(getTotalSizeOfFilesInDir(file));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return size;
    }

    /**
     * 深度搜索遍历文件夹
     * 
     * @param dirPath
     * @param list
     */
    public static void dfsListFile(String dirPath, List<String> list) {
        File file = new File(dirPath);
        File[] files = file.listFiles();
        for (File tmpFile : files) {
            if (tmpFile.isDirectory()) {
                dfsListFile(tmpFile.getAbsolutePath(), list);
            } else {
                list.add(tmpFile.getAbsolutePath());
            }
        }
    }

    /**
     * 广度搜索遍历文件夹
     * 
     * @param dirPath
     * @param list
     */
    public static void bfsListFile(String dirPath, List<String> list) {
        File file = new File(dirPath);
        File[] fs = file.listFiles();
        Queue<File> queue = new LinkedList<>();

        // 遍历第一层
        for (File f : fs) {
            // 把第一层文件夹加入队列
            if (f.isDirectory()) {
                queue.offer(f);
            } else {
                list.add(f.getAbsolutePath());
            }
        }
        // 逐层搜索下去
        while (!queue.isEmpty()) {
            // 从队列头取一个元素
            File fileTemp = queue.poll();
            File[] fileListTemp = fileTemp.listFiles();
            for (File f : fileListTemp) {
                if (f.isDirectory()) {
                    queue.offer(f);
                } else {
                    list.add(f.getAbsolutePath());
                }
            }
        }

    }

    public static void main(String[] args) {
        // System.out.println("广度搜索");
        // List<String> list = new ArrayList<>();
        // bfsListFile("E:\\spring-cloud-example\\server-consumer", list);
        // for (String string : list) {
        // System.out.println(string);
        // }
        // System.out.println("深度搜索");
        // list.clear();
        // dfsListFile("E:\\spring-cloud-example\\server-consumer", list);
        // for (String string : list) {
        // System.out.println(string);
        // }

        unZip(new File("D:\\360安全浏览器下载\\weui-master.zip"), new File("E:\\zsk"));

    }
}
